package com.cloud.pole.user.service.account.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cloud.pole.api.user.UserAccountApi;
import com.cloud.pole.common.constant.CommonConstants;
import com.cloud.pole.common.exception.BaseException;
import com.cloud.pole.common.util.ListUtils;
import com.cloud.pole.common.util.UUIDUtils;
import com.cloud.pole.common.util.jwt.IJWTInfo;
import com.cloud.pole.common.util.jwt.JwtTokenUtil;
import com.cloud.pole.user.biz.BaseUserBiz;
import com.cloud.pole.user.biz.account.UserAccountBiz;
import com.cloud.pole.user.biz.account.UserAccountDetailBiz;
import com.cloud.pole.user.biz.account.UserAccountDetailTypeBiz;
import com.cloud.pole.user.biz.account.UserAccountTypeBiz;
import com.cloud.pole.user.model.entity.BaseUser;
import com.cloud.pole.user.model.entity.account.UserAccount;
import com.cloud.pole.user.model.entity.account.UserAccountDetail;
import com.cloud.pole.user.model.entity.account.UserAccountDetailType;
import com.cloud.pole.user.model.entity.account.UserAccountType;
import com.cloud.pole.user.model.vo.account.UserAccountVo;
import com.cloud.pole.user.service.account.UserAccountService;
import lombok.extern.slf4j.Slf4j;

/*
*2019年1月30日
*cloud-user
*author:frank-chen
*/
@Service
@Slf4j
public class UserAccountServiceImpl implements UserAccountService {
	@Autowired
    private BaseUserBiz userBiz;
	
	@Autowired
    private UserAccountBiz userAccountBiz;
	
	@Autowired
    private UserAccountTypeBiz userAccountTypeBiz;
	
	@Autowired
    private UserAccountDetailTypeBiz userAccountDetailTypeBiz;
	
	@Autowired
    private UserAccountDetailBiz userAccountDetailBiz;
	
	@Override
	public int handleBalance(Integer typeId, Long userId, String userName, String objectId, Integer objectTypeId,
			BigDecimal amount, Long srcUserId, String srcUserName, String srcRealName, String note) throws Exception {
		// TODO Auto-generated method stub
		int status = 0;
		int direction = 0;
		//判断typeId是否正确
		UserAccountType userAccountType = userAccountTypeBiz.selectByTypeId(typeId);
		if(userAccountType == null || userAccountType.getTypeStatus() != 1) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "typeId错误");
		}
		//判断objectTypeId是否正确
		UserAccountDetailType userAccountDetailType = userAccountDetailTypeBiz.selectByDetailTypeId(objectTypeId);
		if(userAccountDetailType == null || userAccountDetailType.getTypeStatus() == null || userAccountDetailType.getTypeStatus() != 1) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "objectTypeId错误");
		}
		direction = userAccountDetailType.getDirectionType();
		//判断用户是否正确
		BaseUser baseUser = userBiz.getUserByUserName(userName);
		if(baseUser == null || baseUser.getUserStatus() != 1 || baseUser.getUserId().longValue() != userId.longValue()) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "用戶错误");
		}
		//判断amount是否正确
		if(amount.compareTo(BigDecimal.ZERO) <= 0) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "金额错误");
		}
		UserAccount userAccount = userAccountBiz.getUserAccountByTypeId(userId, typeId);
		if(userAccount == null) {
			//新增账号
			userAccount = new UserAccount();
			userAccount.setAccountBalance(BigDecimal.ZERO);
			userAccount.setAccountNumber(Long.toString(userId) + UUIDUtils.generateShortUuid15() + Long.toString(System.currentTimeMillis()));
			userAccount.setAccountStatus(UserAccount.USER_ACCOUNT_STATUS_OK);
			userAccount.setCreateTime(new Date());
			userAccount.setTypeId(typeId);
			userAccount.setUserId(baseUser.getUserId());
			userAccount.setUserName(baseUser.getUserName());
			userAccountBiz.insertUseGeneratedKeys(userAccount);
		}
	    if(direction == UserAccount.BALANCE_DIRECTION_REDUCE) {
		    if(userAccount.getAccountBalance().compareTo(amount) < 0 ) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "余额不足");
		    }
	    }
		//增加余额
		synchronized(this){
			//写入日志
			UserAccountDetail userAccountDetail = new UserAccountDetail();
			userAccountDetail.setAccountId(userAccount.getAccountId());
			userAccountDetail.setBeforeAmount(userAccount.getAccountBalance());
			userAccountDetail.setCreateTime(new Date());
			userAccountDetail.setNote(note);
			userAccountDetail.setObjectId(objectId);
			userAccountDetail.setObjectNote("");
			userAccountDetail.setObjectTypeId(objectTypeId);
			userAccountDetail.setSrcRealName(srcRealName);
			userAccountDetail.setSrcUserId(srcUserId);
			userAccountDetail.setSrcUserName(srcUserName);
			userAccountDetail.setTypeId(typeId);
			userAccountDetail.setUserId(userId);
			userAccountDetail.setUserName(userName);
			
			//增加余额
			if(direction == UserAccount.BALANCE_DIRECTION_PLUS) {
				userAccountDetail.setAmount(amount);
				userAccountDetail.setAfterAmount(userAccount.getAccountBalance().add(amount));
				userAccountDetailBiz.insertSelective(userAccountDetail);
			    status = userAccountBiz.updateBalancePlus(userId, typeId, amount);
			}
			//减少余额
			else if(direction == UserAccount.BALANCE_DIRECTION_REDUCE) {
				userAccountDetail.setAmount(BigDecimal.ZERO.subtract(amount));
				userAccountDetail.setAfterAmount(userAccount.getAccountBalance().subtract(amount));
				userAccountDetailBiz.insertSelective(userAccountDetail);
			    status = userAccountBiz.updateBalanceReduce(userId, typeId, amount);
			}
		}
		return status;
	}

	@Override
	public List<UserAccountApi> getAccountList(String token) throws Exception {
		IJWTInfo jwtInfo = JwtTokenUtil.getInfoFromToken(token);
		Long userId = Long.parseLong(jwtInfo.getId());
		// TODO Auto-generated method stub
		/**
		 * 如果账号没有需要生成账号
		 */
		List<UserAccountType> accountTypeList = userAccountTypeBiz.selectAccountTypeValidList();
		for(UserAccountType accountType : accountTypeList) {
			UserAccount userAccount = userAccountBiz.getUserAccountByTypeId(userId, accountType.getTypeId());
			if(userAccount == null) {
				//新增账号
				userAccount = new UserAccount();
				userAccount.setAccountBalance(BigDecimal.ZERO);
				userAccount.setAccountNumber(Long.toString(userId) + UUIDUtils.generateShortUuid15() + Long.toString(System.currentTimeMillis()));
				userAccount.setAccountStatus(UserAccount.USER_ACCOUNT_STATUS_OK);
				userAccount.setCreateTime(new Date());
				userAccount.setTypeId(accountType.getTypeId());
				userAccount.setUserId(userId);
				userAccount.setUserName(jwtInfo.getUniqueName());
				userAccountBiz.insertUseGeneratedKeys(userAccount);
			}
		}
		List<UserAccountVo> userAccountList  = userAccountBiz.selectBalanceListByUserId(Long.parseLong(jwtInfo.getId()));
		List<UserAccountApi> userAccountApiList = ListUtils.copyListProperties(userAccountList, UserAccountApi.class);
		return userAccountApiList;
	}

	@Override
	public String getAccountTypeName(Integer typeId) throws Exception {
		// TODO Auto-generated method stub
		String typeName ="";
		UserAccountType userAccountType = userAccountTypeBiz.selectByTypeId(typeId);
		if(userAccountType != null) {
			typeName = userAccountType.getTypeName();
		}
		return typeName;
	}

	@Override
	public UserAccountVo getUserAccount(String token, Long accountId) throws Exception {
		IJWTInfo jwtInfo = JwtTokenUtil.getInfoFromToken(token);
		Long userId = Long.parseLong(jwtInfo.getId());
		UserAccount userAccount = userAccountBiz.selectByPrimaryKey(accountId);
		if(userAccount == null || userAccount.getUserId().longValue() != userId.longValue()) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "accountId错误");
		}		
		UserAccountType userAccountType = userAccountTypeBiz.selectByTypeId(userAccount.getTypeId());
		if(userAccountType == null || userAccountType.getTypeStatus() != UserAccountType.TYPE_STATUS_VALID) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "typeId错误");
		}			
		UserAccountVo userAccountVo = new UserAccountVo();
		BeanUtils.copyProperties(userAccount, userAccountVo);
		userAccountVo.setTypeName(userAccountType.getTypeName());
		userAccountVo.setWithdrawFlag(userAccountType.getWithdrawFlag());
		return userAccountVo;
	}
}
